﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Drawing;

namespace lesson1
{
    class MyGDIClass
    {
        [DllImport("Gdi32.dll")]
        public static extern int SetPixel(IntPtr hDC, int x, int y, int color);
        [DllImport("Gdi32.dll")]
        public static extern int GetPixel(IntPtr hDC, int x, int y);


        public static void DDA(IntPtr hDC,int x0,int y0,int x1,int y1)
        {
            float maxLength = Math.Max(Math.Abs(x1 - x0), Math.Abs(y1 - y0));
            float increx = (x1 - x0) / maxLength,
                increy = (y1 - y0) / maxLength;
            float x = x0, y = y0;
            for (int i = 0; i < maxLength; i++)
            {
                x += increx;
                y += increy;
                SetPixel(hDC, (int)(x + 0.5), (int)(y + 0.5),0);
            }
        }

        public static void Bresenham(IntPtr hDC, int x0, int y0, int x1, int y1)
        {
            
            int dx = Math.Abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
            int dy = -Math.Abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
            int err = dx + dy, e2; /* error value e_xy */

            for (; ; )
            {  /* loop */
                SetPixel(hDC, x0, y0, 0);
                if (x0 == x1 && y0 == y1) break;
                e2 = 2 * err;
                if (e2 >= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
                if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
            }
        }

        public static void MidCircle(IntPtr hDC, int centx, int centy, int r)
        {
            int d = 1 - r, x = 0, y = r;
            WholeCircle(hDC, centx, centy, x, y);
            while (x <= y)
            {
                if (d < 0)
                {
                    d += (x << 1) + 3;
                    x++;
                }
                else
                {
                    d += ((x - y) << 1) + 5;
                    x++;
                    y--;
                }
                WholeCircle(hDC, centx, centy, x, y);
            }
        }
        static void WholeCircle(IntPtr hDC, int centx,int centy,int x,int y)
        {
            SetPixel(hDC, centx + x, centy + y, 0);
            SetPixel(hDC, centx - x, centy + y, 0);
            SetPixel(hDC, centx - x, centy - y, 0);
            SetPixel(hDC, centx + x, centy - y, 0);

            SetPixel(hDC, centx + y, centy + x, 0);
            SetPixel(hDC, centx - y, centy + x, 0);
            SetPixel(hDC, centx - y, centy - x, 0);
            SetPixel(hDC, centx + y, centy - x, 0);
        }

        public static void BresenhamCircle(IntPtr hDC, int centx, int centy, int r)
        {
            int d = 2 * (1 - r), x = 0, y = r;
            WholeCircle(hDC, centx, centy, x, y);

            while (x<=y)
            {
                int hd = ((d + y) << 1) - 1;
                if (hd < 0)
                {
                    x++;
                    d += (x << 1) + 1;
                }
                else
                {
                    x++;
                    y--;
                    d += (x - y + 1) << 1;
                }
                WholeCircle(hDC, centx, centy, x, y);
            }
        }

        public static void CubicSpline(IntPtr hDC,List<Point> ps)
        {
            CubicSpline cs = new CubicSpline(ps);
            cs.draw(hDC);
        }
        public static void SeedFill(IntPtr hDC, int boundcolor, Point pointseed, int fillcolor)
        {
            Stack<Point> fillps = new System.Collections.Generic.Stack<Point>();
            PushSeed(hDC,boundcolor,pointseed,fillcolor,fillps);
            
            while (fillps.Count > 0)
            {
                Point current = fillps.Pop();
                SetPixel(hDC, current.X, current.Y, fillcolor);

                PushSeed(hDC, boundcolor, new Point(current.X,current.Y+1), fillcolor, fillps);
                PushSeed(hDC, boundcolor, new Point(current.X, current.Y - 1), fillcolor, fillps);
                PushSeed(hDC, boundcolor, new Point(current.X+1, current.Y), fillcolor, fillps);
                PushSeed(hDC, boundcolor, new Point(current.X-1, current.Y ), fillcolor, fillps);

            }
        }
        static void PushSeed(IntPtr hDC, int boundcolor, Point pointseed, int fillcolor,Stack<Point> s)
        {
            if (pointseed.X < 0 || pointseed.Y < 0|| pointseed.X>1080||pointseed.Y>960) return;
            int c = GetPixel(hDC, pointseed.X, pointseed.Y);
            if (c != fillcolor && c != boundcolor)
            {
                s.Push(pointseed);
            }
        }
       
        public static void ScanlineFill(IntPtr hDC, List<Point> ps, int fillcolor)
        {
            ScanlineFillHelper.Fill(hDC, ps, fillcolor);
        }
       
    }
}
